﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Facebook_Graph_Toolkit.GraphApi;
using JSON;
using Facebook_Graph_Toolkit.FacebookObjects;
using System.Web;
using System.Reflection;

namespace Facebook_Graph_Toolkit.Helpers {
    internal static class ApiCaller {
        private static string FormatConnectionURL(string Connection, string ID, string AccessToken, int? Offset, int? Limit) {
            string URL = string.Format("https://graph.facebook.com/{0}/{1}?access_token={2}", ID, Connection, AccessToken);
            if (Offset.HasValue) URL += "&offset=" + Offset.ToString();
            if (Limit.HasValue) URL += "&limit=" + Limit.ToString();
            return URL;
        }

        private static IList<T> GetConnectionObjects<T>(string Connection, string ID, string AccessToken, int? Offset, int? Limit) 
        where T: GraphApiObject{
            List<T> Objects = new List<T>();
            string URL = FormatConnectionURL(Connection, ID, AccessToken, Offset, Limit);
            JsonObject JO = new JsonObject(Helpers.WebResponseHelper.GetWebResponse(URL));
            if (JO["data"] == null) return Objects;
            JsonArray dataArray = (JsonArray)JO["data"];
            ConstructorInfo MI = typeof(T).GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof(JsonObject) }, null);
            if (MI == null) throw new Exception("Facebook Graph Toolkit Error: Constructor not found");
            foreach (JsonObject DataJO in dataArray) {
                object Instance = MI.Invoke(new object[] { DataJO });
                Objects.Add((T)Instance);
            }
            return Objects;
        }

        
        internal static IList<Photo> GetPhotos(string ID, string AccessToken, int? Offset, int? Limit){
            return GetConnectionObjects<Photo>("photos", ID, AccessToken, Offset, Limit);
        }
        internal static IList<Album> GetAlbums(string ID,string AccessToken, int? Offset, int? Limit) {
            return GetConnectionObjects<Album>("albums", ID, AccessToken, Offset, Limit);
        }
        internal static IList<Post> GetPosts(string ID, string AccessToken, int? Offset, int? Limit) {
            return GetConnectionObjects<Post>("posts", ID, AccessToken, Offset, Limit);
        }
        internal static IList<Post> GetFeed(string ID, string AccessToken, int? Offset, int? Limit) {
            return GetConnectionObjects<Post>("feed", ID, AccessToken, Offset, Limit);
        }
        internal static IList<NameIDPair> GetFriends(string ID, string AccessToken, int? Offset, int? Limit) {
            return GetConnectionObjects<NameIDPair>("friends", ID, AccessToken, Offset, Limit);
        }
        internal static IList<Post> GetHome(string ID, string AccessToken, int? Offset, int? Limit) {
            return GetConnectionObjects<Post>("home", ID, AccessToken, Offset, Limit);
        }
        internal static IList<Link> GetLinks(string ID, string AccessToken, int? Offset, int? Limit) {
            return GetConnectionObjects<Link>("links", ID, AccessToken, Offset, Limit);
        }
        internal static IList<StatusMessage> GetStatusMessages(string ID, string AccessToken, int? Offset, int? Limit) {
            return GetConnectionObjects<StatusMessage>("statuses", ID, AccessToken, Offset, Limit);
        }
        internal static IList<Note> GetNotes(string ID, string AccessToken, int? Offset, int? Limit) {
            return GetConnectionObjects<Note>("notes", ID, AccessToken, Offset, Limit);
        }
        internal static IList<LikedPage> GetLikedPages(string ID, string AccessToken, int? Offset, int? Limit) {
            return GetConnectionObjects<LikedPage>("likes", ID, AccessToken, Offset, Limit);
        }
        internal static IList<GroupBookmark> GetGroups(string ID, string AccessToken, int? Offset, int? Limit) {
            return GetConnectionObjects<GroupBookmark>("groups", ID, AccessToken, Offset, Limit);
        }
        internal static IList<UserEvent> GetEvents(string ID, string AccessToken, int? Offset, int? Limit) {
            return GetConnectionObjects<UserEvent>("events", ID, AccessToken, Offset, Limit);
        }
        internal static IList<AppReview> GetAppReviews(string ID, int? Offset, int? Limit) {
            return GetConnectionObjects<AppReview>("reviews", ID, "", Offset, Limit);
        }
        internal static IList<Notification> GetNotifications(string ID, string AccessToken, int? Offset, int? Limit, bool UnreadOnly) {
            IList<Notification> _List = new List<Notification>();

            string URL = FormatConnectionURL("notifications", ID, AccessToken, Offset, Limit);
            if (!UnreadOnly) URL += "&include_read=1";
            JsonObject JO = new JsonObject(Helpers.WebResponseHelper.GetWebResponse(URL));
            JsonArray dataArray = (JsonArray)JO["data"];
            if (dataArray == null) return _List;
            foreach (JsonObject _JO in dataArray) {
                _List.Add(new Notification(_JO));
            }
            return _List;
        }
        internal static IList<GroupMember> GetGroupMembers(string ID, string AccessToken, int? Offset, int? Limit) {
            return GetConnectionObjects<GroupMember>("members", ID, AccessToken, Offset, Limit);
        }
        internal static IList<Comment> GetComments(string ID, string AccessToken, int? Offset, int? Limit) {
            return GetConnectionObjects<Comment>("comments", ID, AccessToken, Offset, Limit);
        }
        internal static JsonArray FqlFresh(string FqlQuery, string AccessToken) {
            string url = string.Format("https://api.facebook.com/method/fql.query?query={0}&format=JSON&access_token={1}", HttpUtility.UrlPathEncode(FqlQuery), AccessToken);
            return new JsonArray(Helpers.WebResponseHelper.GetWebResponse(url));
        }
    }
}
